/**
 * @author phi
 */

var COLOR_LIST = [
    // "rgba(  0,   0,   0, 1)", // black
    // "rgba(255, 255, 255, 1)", // white
    "rgba(255,   0,   0, 1)", // red
    "rgba(  0, 255,   0, 1)", // green
    "rgba(  0,   0, 255, 1)", // blue
    "rgba(255, 255,   0, 1)", // yellow
    "rgba(  0, 255, 255, 1)", // cyan
    "rgba(255,   0, 255, 1)", // magenta
];

var GRAVITY = Vector3();
GRAVITY.set(-Math.cos(Math.PI*0.5)*2.0, Math.sin(Math.PI*0.5)*2.0);
var BALL_MAX_NUM = 16;
var FPS = 1000/30;

var ballList = [];
var canvas;
var context;

/**
 * ロード
 */
window.onload = function()
{
    // キャンバス取得
    canvas = document.getElementById("my-canvas");
    context = canvas.getContext("2d");
    
    // ボールを生成
    for (var i=0; i<BALL_MAX_NUM; ++i) {
        var temp = ballList[i] = Ball();
        temp.init();
        temp.pos.set( Math.random()*640, Math.random()*480 );
    }
    
    // 更新関数を登録
    var run = function() {
        update();
        draw();
        setTimeout(run, FPS);
    }
    setTimeout(run, FPS)
};

/**
 * 更新
 */
var update = function()
{
    for (var i=0; i<ballList.length; ++i) {
        ballList[i].update();
    }
    
    return ;
}

/**
 * 描画
 */
var draw = function()
{
    // 画面クリア
    context.fillStyle = "rgba(0, 0, 0, 1)";
    context.fillRect(0, 0, canvas.width, canvas.height);
    // 描画
    for (var i=0; i<ballList.length; ++i) {
        ballList[i].draw();
    }
}


/**
 * 
 */
var Ball = (function(member) {
    
    var TempClass = function(){
        return new TempClass.prototype.creator();
    };
    
    TempClass.prototype = member;
    TempClass.prototype.creator = function(){ return this; };
    TempClass.prototype.creator.prototype = TempClass.prototype;
    
    return TempClass;
})({
    pos     : undefined,
    velocity: undefined,
    radius  : undefined,
    color   : 0,
    
    /**
     * 初期化
     */
    init: function() {
        // 初期値をセット
        this.pos = Vector3();
        this.pos.x = this.pos.y = this.pos.z = 0;
        this.velocity = Vector3();
        // ランダムな報告に加速度を設定
        var angle = Math.random()*6.28;
        this.velocity.x = Math.cos(angle)*8;
        this.velocity.y = Math.sin(angle)*8;
        this.velocity.z = 0;
        // 半径
        this.radius = 32;
        
        // 色をランダムにセット
        this.setRandomColor();
    },
    
    /**
     * 更新
     */
    update: function(){
        this.pos.add(this.velocity);
        this.velocity.add(GRAVITY);
        // this.velocity.y += 2.0;
        
        var left    =   0 + this.radius;
        var right   = 640 - this.radius;
        var top     =   0 + this.radius;
        var bottom  = 480 - this.radius;
        if (this.pos.x <   left) { this.pos.x =   left; this.velocity.x *= -0.8;  }
        if (this.pos.x >  right) { this.pos.x =  right; this.velocity.x *= -0.8;  }
        if (this.pos.y <    top) { this.pos.y =    top; this.velocity.y *= -0.8;  }
        if (this.pos.y > bottom) { this.pos.y = bottom; this.velocity.y *= -0.8;  }
        
        for (var i=0; i<ballList.length; ++i) {
            var other = ballList[i];
            
            if (other == this) { continue ; }
            
            if (Ball.collision(this, other)) { this.reflect(other); }
        }
    },
    
    /**
     * 反射
     */
    reflect : function(other)
    {
        // 球同士でできる面の法線
        var ndp = Vector3.sub(this.pos, other.pos);
        ndp.normalize();
        // 押し出す
        var temp = Vector3.mul(ndp, this.radius + other.radius);
        temp.add(other.pos);
        this.pos = temp;
        
        // 速度の向きを変更
        var new_velocity = Vector3.reflect(this.velocity, ndp);
        new_velocity.mul(0.8);
        this.velocity = new_velocity;
        
        // 相手側の向きも変更
        var new_velocity2 = Vector3.reflect(other.velocity, Vector3.negative(ndp))
        new_velocity2.mul(0.8)
        other.veloctity = new_velocity2;
        
        return this;
    },

    /**
     * 描画
     */
    draw: function()
    {
        context.fillStyle = this.color;
        // 円描画
        context.beginPath();
        context.arc( this.pos.x, this.pos.y, this.radius, 0, Math.PI*2, false );
        context.fill();
        
        return this;
    },
    
    /**
     * 色をランダムにセット
     */
    setRandomColor : function()
    {
        this.color = COLOR_LIST[ Math.floor(Math.random()*COLOR_LIST.length) ];
        
        return this;
    }
    
});

/**
 * ボール同士の衝突判定
 */
Ball.collision = function(ball0, ball1)
{
    // ball1 から ball0 へのベクトル
    var v = Vector3.sub(ball0.pos, ball1.pos);
    // ボールの実際の距離の二乗
    var len = (ball0.radius+ball1.radius) * (ball0.radius+ball1.radius);
    
    // 衝突判定
    if (v.lengthSquare() < len) {
        return true;
    }
    
    return false;
};























